home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Utilities / Text Processing / Alpha / Tcl / Modes / HTML and CSS Modes / cssMode.tcl next >
Encoding:
Text File  |  1997-11-02  |  12.6 KB  |  407 lines  |  [TEXT/ALFA]

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  CSS mode - tools for editing CSS documents
  4.  # 
  5.  #  FILE: "cssMode.tcl"
  6.  #                                    created: 97-03-01 17.02.41 
  7.  #                                last update: 97-10-29 19.31.49 
  8.  #  Author: Johan Linde
  9.  #  E-mail: <jl@theophys.kth.se>
  10.  #     www: <http://bach.theophys.kth.se/~jl/Alpha.html>
  11.  #  
  12.  # Version: 1.0.3
  13.  # 
  14.  # Copyright 1997 by Johan Linde
  15.  #  
  16.  # This software may be used freely, and distributed freely, as long as the 
  17.  # receiver is not obligated in any way by receiving it.
  18.  #  
  19.  # If you make improvements to this file, please share them!
  20.  # 
  21.  # ###################################################################
  22.  ##
  23.  
  24. # Defining CSS mode
  25.  
  26. alpha::mode CSS 1.0.3 cssMenu {*.css *.CSS} cssMenu {
  27.     addMenu cssMenu •150
  28. } uninstall {
  29.     set __dir [file dirname [procs::find cssMenu]]
  30.     catch {removeFile $__dir:cssMode.tcl}
  31.     if {[procs::find htmlMenu] == ""} {
  32.         catch {removeFile $__dir:hctsmsl.tcl}
  33.         catch {removeFile $__dir:hctsmslShared.tcl}
  34.         catch {removeFile $__dir:hctsmslMenu.tcl}
  35.         catch {removeFile "$HOME:Help:HTML Help"}
  36.     }
  37. } maintainer {
  38.     "Johan Linde" jl@theophys.kth.se <http://www.theophys.kth.se/~jl/Alpha.html>
  39. } help {file "HTML Help"}
  40.  
  41. proc cssMenu {} {}
  42.  
  43. newPref f wordWrap 0 CSS
  44. newPref v wordBreak {\w+} CSS
  45. newPref v wordBreakPreface {\W} CSS
  46. newPref v commentColor red CSS
  47. newPref v keywordColor blue CSS
  48. newPref v htmlColor magenta CSS
  49. newPref f elecRBrace 1 CSS
  50. newPref f elecLBrace 1 CSS
  51. newPref f electricSemi 1 CSS
  52. newPref f openNonTextFile 1 CSS
  53.  
  54. # Coloring
  55. proc cssColoring {} {
  56.     global CSSmodeVars
  57.     regModeKeywords -b {/*} {*/} -c $CSSmodeVars(commentColor) -k $CSSmodeVars(keywordColor) CSS {
  58.     font-family font-style font-variant font-weight font-size font 
  59.     color background-color background-image background-repeat background-attachment
  60.     background-position background word-spacing letter-spacing text-decoration
  61.     vertical-align text-transform text-align text-indent line-height
  62.     margin-top margin-right margin-bottom margin-left margin padding-top padding-right
  63.     padding-bottom padding-left padding border-top-width border-right-width
  64.     border-bottom-width border-left-width border-width border-color border-style
  65.     border-top border-right border-bottom border-left border width height float clear
  66.     display white-space list-style-type list-style-image list-style-position list-style
  67.     @import important
  68.     link visited active first-letter first-line}
  69.     regModeKeywords -a -k $CSSmodeVars(htmlColor) CSS [cssGetHtmlWords]
  70. }
  71.  
  72. # Load other CSS mode files.
  73. foreach tmp {hctsmsl hctsmslShared hctsmslMenu} {
  74.     if {[info exists htmlModeIsLoaded] && ($tmp == "hctsmslMenu" || $tmp == "hctsmslShared")} {continue}
  75.     if {$tmp == "hctsmsl" && [info exists cssUnits]} {continue}
  76.     if { [catch {${tmp}.tcl}] } {
  77.         beep
  78.         alertnote "Loading of ${tmp}.tcl failed"
  79.         return
  80.     }
  81. }
  82.  
  83. # Clean up after version 1.0b1
  84. if {[info exists htmlMenuKey]} {
  85.     foreach tmp [array names htmlMenuKey] {
  86.         removeArrDef htmlMenuKey $tmp
  87.     }
  88.     htmlWriteMenuKeys
  89. }
  90.  
  91. proc cssHTMLelement {elem} {
  92.     insertText $elem
  93. }
  94.  
  95.  
  96. proc CSSDividingLine {} {
  97.     insertText "/*=============================================================================*/\r"
  98. }
  99. bind 'l' <C> CSSDividingLine CSS
  100.  
  101.  
  102.  
  103. proc CSS::electricSemi {} {
  104.     global CSSmodeVars
  105.     if {[isSelection]} {deleteSelection}
  106.     if {$CSSmodeVars(electricSemi)} {
  107.         insertText ";\r"
  108.         text::genericIndent
  109.     } else {
  110.         insertText ";"
  111.     }
  112. }
  113.  
  114. proc CSS::parseFuncs {} {
  115.     set pos 0
  116.     set funcExpr {^[ \t]*([^\r\{]+)\{}
  117.     while {[set res [search -s -f 1 -r 1 -i 0 -n $funcExpr $pos]] != ""} {
  118.         if {[regexp $funcExpr [getText [car $res] [cadr $res]] dummy word]} {
  119.             lappend m [list $word [car $res]]
  120.         }
  121.         set pos [cadr $res]
  122.     }
  123.     return [join [lsort -ignore $m]]
  124. }
  125.  
  126. #===============================================================================
  127. # Key bindings
  128. #===============================================================================
  129.  
  130. # Define key bindings from html menu.
  131. proc cssBindingsFromMenu {me tmplist} {
  132.     global htmlMenuKey html${me}Sub
  133.     upvar $tmplist tmp
  134.     foreach it [set html${me}Sub] {
  135.         if {[llength $it] > 2} {
  136.             set elem [lindex $it 2]            
  137.              if {[info exists htmlMenuKey(${me}/[lindex $it 1])]} {
  138.                 set key $htmlMenuKey(${me}/[lindex $it 1])
  139.             } else {
  140.                 set key [lindex $it 0]
  141.             }
  142.             cssBindOneKey $key $elem "" tmp
  143.         }
  144.     }
  145. }
  146.  
  147. proc cssBindOneKey {key elem {un ""} {tmplist ""}} {
  148.      set funcKeys {Enter 0x0d 0x09 Clear F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
  149.      Help 0x08 Del Home End Pgup Pgdn}
  150.  
  151.     set mods ""
  152.     if {[regexp {<B} $key]} {append mods z}
  153.     if {[regexp {<I} $key]} {append mods o}
  154.     if {[regexp {<U} $key]} {append mods s}
  155.     if {[regexp {<O} $key]} {append mods c}
  156.     set key1 ""
  157.     if {[regexp {/(.)} $key a b]} {
  158.         if {[string compare $b a] == -1 || [string compare $b z] == 1} {
  159.             set key1 '[string tolower $b]'
  160.         } else {
  161.             set key1 [lindex $funcKeys [expr [text::Ascii $b] - 97]]
  162.         }
  163.     }
  164.     if {$key1 == ""} {return}
  165.     if {[string range $key1 0 1] == "0x"} {
  166.         set cmd ${un}ascii
  167.     } else {
  168.         set cmd ${un}bind
  169.     }
  170.     eval [list $cmd $key1 <$mods> "cssHTMLelement $elem" CSS]
  171.     if {$tmplist != ""} {
  172.         upvar $tmplist tmp
  173.         append tmp [list $cmd $key1 <$mods> "cssHTMLelement $elem" CSS] \r
  174.     }
  175. }
  176.  
  177. # Redefine key bindings when changed in HTML menu.
  178. proc cssReBindKey {meny keyItems} {
  179.     global html${meny}Sub
  180.     set items [set html${meny}Sub]
  181.     foreach it $keyItems {
  182.         set it0 [lindex $it 0]
  183.         foreach it1 $items {
  184.             if {[lindex $it1 1] == $it0} {
  185.                 set elem [lindex $it1 2]
  186.                 break
  187.             }
  188.         }
  189.         # Skip those which aren't html elements
  190.         if {[llength $it1] < 3} {continue}
  191.         cssBindOneKey [lindex $it 1] $elem un
  192.         cssBindOneKey [lindex $it 2] $elem
  193.     }
  194. }
  195.  
  196. proc cssMenuKeys {} {
  197.     global htmlMenuKey
  198.     set rebuildCSS 0
  199.     set somethingModified 0
  200.     htmlReadMenuKeys
  201.     htmlSetKeysInMenu CSS
  202.     if {$somethingModified} {htmlWriteMenuKeys}
  203.     catch {unset htmlMenuKey}
  204.     if {$rebuildCSS} {cssRebuildMenu}
  205. }
  206.  
  207. #===============================================================================
  208. # Menu handling
  209. #===============================================================================
  210.  
  211. set htmlCSSSub [concat [lrange $htmlStyleSub 3 end] {"(-" {"<O<U/S" "Reload in Browser"} {"<O/c" "Word Complete"} {"" "Colors…"} {"" "Key Bindings…"} {"" "Preferences…"}}]
  212.  
  213. proc cssBuildMenu {} {
  214.     global cssMenu htmlMenuKey
  215.     if {[catch {htmlReadCache "CSS menu cache" css}]} {
  216.         htmlReadMenuKeys
  217.         set me [htmlBuildOneMenu CSS]
  218.         menu -M CSS -p cssMenuItem -m -n $cssMenu $me
  219.         set h {menu -M CSS -p cssMenuItem -m -n $cssMenu}
  220.         lappend h $me
  221.         htmlSaveCache "CSS menu cache" $h css
  222.     }
  223.     catch {unset htmlMenuKey}
  224. }
  225.  
  226. proc cssRebuildMenu {} {
  227.     htmlDeleteCache "CSS menu cache"
  228.     cssBuildMenu
  229. }
  230.  
  231. proc cssMenuItem {menu item} {
  232.     switch $item {
  233.         "Reload in Browser" {cssReloadinBrowser}
  234.         "Word Complete" {cssWordComplete}
  235.         Colors {htmlColors}
  236.         "Key Bindings" {cssMenuKeys}
  237.         "Preferences" {CSSmodifyFlags}
  238.         Import {cssDialog @import}
  239.         Display {cssDialog Display}
  240.         default {cssDialog [join [string tolower $item] -]}
  241.     }
  242. }
  243.  
  244. #===============================================================================
  245. # Cmd-double-click
  246. #===============================================================================
  247.  
  248. proc CSS::DblClick {from to} {
  249.     HTML::DblClick $from $to
  250. }
  251.  
  252. #===============================================================================
  253. # Reload in Browser
  254. #===============================================================================
  255.  
  256. proc cssReloadinBrowser {} {
  257.     global browserSig HTMLmodeVars
  258.     if {$browserSig != "MOSS" && $browserSig != "MSIE"} {
  259.         beep; message "Works only with Netscape and MSIE."; return
  260.     }
  261.     # returns window ids
  262.     if {![regexp {\[([0-9]+)} [AEBuild -r '$browserSig' WWW! LSTW] dum winnum]} {beep; message "No browser window."; return}
  263.     if {[winDirty]} {
  264.         if {[set ask [askyesno -c "Save '[lindex [winNames] 0]'?"]] == "yes"} {
  265.             save
  266.         } elseif {$ask == "cancel"} {
  267.             return
  268.         }
  269.     }
  270.     # returns window info
  271.     regexp {\[([^ ]+)} [AEBuild -r '$browserSig' WWW! WNFO ---- $winnum] dum winurl
  272.     set winurl [string trim $winurl "“”,"]
  273.     if {$winurl == "'TEXT'()"} {beep; message "Empty browser window."; return}
  274.     # reloads window
  275.     set flgs ""
  276.     if {$browserSig == "MSIE"} {set flgs "FLGS 1"}
  277.     eval AEBuild '$browserSig' WWW! OURL ---- "“$winurl”" $flgs
  278.     if {![info exists HTMLmodeVars(browseInForeground)] || $HTMLmodeVars(browseInForeground)} {switchTo '$browserSig'}
  279. }
  280.  
  281.  
  282. #===============================================================================
  283. # Preferences
  284. #===============================================================================
  285.  
  286. proc CSSmodifyFlags {} {
  287.     global CSSmodeVars modifiedModeVars colorInds
  288.     set colors {none blue cyan green magenta red white yellow}
  289.     foreach c [lsort [array names colorInds]] {
  290.         if {[regexp {color} $c]} {lappend colors $c}
  291.     }
  292.     set box "-t {CSS mode Preferences} 100 10 450 30 \
  293.     -c {Electric left braces} $CSSmodeVars(elecLBrace) 10 35 450 50 \
  294.     -c {Electric right braces} $CSSmodeVars(elecRBrace) 10 55 450 70 \
  295.     -c {Electric semicolon} $CSSmodeVars(electricSemi) 10 75 450 90 \
  296.     -c {Cmd-double-clicking on non-text file link opens file} $CSSmodeVars(openNonTextFile) 10 95 450 110 \
  297.     -t {Color of keywords:} 10 115 150 130 \
  298.     -m [list [concat $CSSmodeVars(keywordColor) $colors]] 160 115 310 135 \
  299.     -t {Color of comments:} 10 140 150 155 \
  300.     -m [list [concat $CSSmodeVars(commentColor) $colors]] 160 140 310 155 \
  301.     -t {Color of HTML:} 10 165 150 180 \
  302.     -m [list [concat $CSSmodeVars(htmlColor) $colors]] 160 165 310 180 \
  303.     -t wordBreak: 10 190 150 205 \
  304.     -e [list $CSSmodeVars(wordBreak)] 155 190 450 205 \
  305.     -t wordBreakPreface: 10 215 150 230 \
  306.     -e [list $CSSmodeVars(wordBreakPreface)] 155 215 450 230"
  307.     set values [eval [concat dialog -w 460 -h 275 -b OK 20 245 85 265 -b Cancel 110 245 175 265 $box]]
  308.     if {[lindex $values 1]} {return}
  309.     set i 1
  310.     foreach flag {elecLBrace elecRBrace electricSemi openNonTextFile keywordColor
  311.     commentColor htmlColor wordBreak wordBreakPreface} {
  312.         global $flag
  313.         incr i
  314.         set val [lindex $values $i]
  315.         if {$CSSmodeVars($flag) != $val} {
  316.             set $flag $val
  317.             set CSSmodeVars($flag) $val
  318.             lappend modifiedModeVars [list $flag CSSmodeVars]
  319.             if {[string match "*Color" $flag]} {cssColoring}
  320.         }
  321.     }
  322.     
  323.     
  324. }
  325.  
  326. #===============================================================================
  327. # Initialization
  328. #===============================================================================
  329.  
  330. set cssVersion 2.0
  331.  
  332. # Define key bindings.
  333. if {[catch {htmlReadCache "CSS keybindings cache" css}]} {
  334.     htmlReadMenuKeys
  335.     message "Defining key bindings…"
  336.     foreach tmp [lrange $htmlSubMenus $htmlStartElements end] {
  337.         cssBindingsFromMenu [lindex $tmp 0] tmplist
  338.     }
  339.     if {[info exists htmlModeIsLoaded]} {
  340.         foreach tmp [array names htmlElemKeyBinding] {
  341.             cssBindOneKey $htmlElemKeyBinding($tmp) $tmp "" tmplist
  342.         }
  343.     } elseif {[file exists $PREFS:HTMLadditions.tcl]} {
  344.         set tmpcid [scancontext create]
  345.         scanmatch $tmpcid {htmlElemKeyBinding} {
  346.             cssBindOneKey [lindex [lindex $matchInfo(line) 1] 2] [lindex $matchInfo(line) 0] "" tmplist
  347.         }
  348.         if {![catch {open $PREFS:HTMLadditions.tcl} tmpfid]} {
  349.             scanfile $tmpcid $tmpfid
  350.             close $tmpfid
  351.         }
  352.         scancontext delete $tmpcid
  353.         catch {unset tmpcid tmpfid}
  354.     }
  355.     htmlSaveCache "CSS keybindings cache" $tmplist css
  356.     unset tmplist
  357.     catch {unset htmlMenuKey}
  358. } else {
  359.     message "Reading key bindings…"
  360. }
  361.  
  362. if {![info exists htmlModeIsLoaded]} {
  363.     set cssHtmlWords {A ADDRESS APPLET AREA B BASE BASEFONT BGSOUND BIG 
  364.         BLINK BLOCKQUOTE BODY BR 
  365.         CAPTION CENTER CITE CODE COL COLGROUP DD DFN DIR DIV DL DT EM EMBED FONT 
  366.         FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME ILAYER IMG INPUT ISINDEX KBD 
  367.         KEYGEN LAYER LI LINK MAP MARQUEE MENU META MULTICOL NOBR NOEMBED NOFRAMES NOLAYER NOSCRIPT 
  368.         OBJECT OL OPTION P PARAM PRE SAMP SCRIPT SELECT SMALL SPACER SPAN STRIKE 
  369.         STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U 
  370.         UL VAR WBR}
  371.     if {[file exists $PREFS:HTMLadditions.tcl]} {
  372.         set tmpcid [scancontext create]
  373.         scanmatch $tmpcid {htmlElemKeyBinding} {
  374.             lappend cssHtmlWords [lindex $matchInfo(line) 0]
  375.         }
  376.         if {![catch {open $PREFS:HTMLadditions.tcl} tmpfid]} {
  377.             scanfile $tmpcid $tmpfid
  378.             close $tmpfid
  379.         }
  380.         scancontext delete $tmpcid
  381.         catch {unset tmpcid tmpfid}
  382.     }
  383. }
  384.  
  385. cssColoring
  386. cssBuildMenu
  387. unset tmp
  388. rename cssBindingsFromMenu ""
  389.  
  390.  
  391. set completions(CSS) {word}
  392.  
  393. set commentCharacters(CSS:General) "/*"
  394. set commentCharacters(CSS:Paragraph) [list "/* " " */" " * "]
  395. set commentCharacters(CSS:Box) [list "/*" 2 "*/" 2 "*" 3]
  396.  
  397.  
  398. if {[info exists htmlModeIsLoaded] && $htmlVersion != $cssVersion} {
  399.     alertnote "Warning: The versions of HTML mode and CSS mode may not be compatible.\
  400.         Always install new versions of HTML mode and CSS mode simultaneously."
  401. }
  402.  
  403. set cssModeIsLoaded 1
  404.  
  405. message "CSS initialization complete."
  406.  
  407.